﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using static System.String;
using System.Xml.Linq;
using WeShare.WeiXin.Common;
using WeShare.WeiXin.Common.EnumKey;
using WeShare.WeiXin.Mp.MsgEntity;
#if !NET40
using System.Threading.Tasks;
#endif
namespace WeShare.WeiXin.Mp
{
    public class MessageFactory
    {
        private MessageFactory() { }
        private static MessageFactory instance;
        private BaseMsgHandler handler;
        private static readonly object locker = new object();
        public static MessageFactory GetInstance<T>() where T : BaseMsgHandler, new()
        {
            if (instance == null)
            {
                lock (locker)
                {
                    if (instance == null)
                    {
                        instance = new MessageFactory();
                        instance.handler = new T();
                    }
                }
            }
            return instance;
        }

        /// <summary>
        /// 根据请求的实例，绑定事件
        /// </summary>
        /// <param name="doc">测试xml，正式运行的时候此参数为空</param>
        /// <param name="baseMsg"></param>
        /// <param name="config"></param>
        /// <returns></returns>
        private static T ConvertWeiXinMessage<T>(XElement doc, BaseMsg baseMsg, EnterParamConfig config) where T : BaseMsg, new()
        {
            var msg = new T();
            #region 获取消息基本信息
            msg.MsgType = baseMsg.MsgType;
            msg.FromUserName = baseMsg.FromUserName;
            msg.CreateTime = baseMsg.CreateTime;
            msg.ToUserName = baseMsg.ToUserName;
            msg.MsgId = baseMsg.MsgId;
            if (config.IsRecordLastTime)
            {
                var key = $"lasttime_{msg.FromUserName}";
                if (OpenApi.redis != null)
                {
                    msg.LastTime = OpenApi.redis.Get<DateTime>(key);
                    //设置本次时间
                    OpenApi.redis.Set(key, DateTime.Now);
                }
                else
                {
                    msg.LastTime = CacheService.Get<DateTime>(key);
                    CacheService.Add(key, DateTime.Now);
                }
            }
            #endregion
            XmlUtil.ToObject(msg, doc, "BaseMsg");
            return msg;
        }
        /// <summary>
        /// 是否重复
        /// </summary>
        /// <param name="doc"></param>
        /// <returns></returns>
        private bool IsRepetition(XElement doc, BaseMsg baseMsg)
        {
            #region 获取消息基本信息
            baseMsg.MsgType = doc.Element("MsgType").Value;
            baseMsg.FromUserName = doc.Element("FromUserName").Value;
            baseMsg.CreateTime = doc.Element("CreateTime").Value;
            baseMsg.ToUserName = doc.Element("ToUserName").Value;
            baseMsg.MsgId = doc.Element("MsgId")?.Value;
            #endregion
            #region 消息排重
            if (baseMsg.MsgType == "event")
            {

                if (!CacheService.ContainsKey(baseMsg.FromUserName + baseMsg.CreateTime))
                {
                    //添加事件消息
                    CacheService.Add(baseMsg.FromUserName + baseMsg.CreateTime, Utils.GetTimeStamp().ToString(), 20);
                    return false;
                }
                else
                {
                    return true;
                }
            }
            else
            {
                if (!CacheService.ContainsKey(baseMsg.MsgId))
                {
                    CacheService.Add(baseMsg.MsgId, Utils.GetTimeStamp().ToString(), 20);
                    return false;
                }
                else
                {
                    return true;
                }
            }
            #endregion
        }

        public string GetResponse(XElement doc, EnterParamConfig config)
        {
            var baseMsg = new BaseMsg();
            if (IsRepetition(doc, baseMsg))
            {
                //消息排重
                return "";
            }

            baseMsg.Param = config;
            var result = handler.BeforeHandler(baseMsg, doc.ToString());
            if (!string.IsNullOrEmpty(result))
            {
                return result;
            }
            var msgtype = (MessageType)Enum.Parse(typeof(MessageType), doc.Element("MsgType").Value.ToUpper());

            switch (msgtype)
            {
                case MessageType.TEXT:
                    return handler.TextHandler(ConvertWeiXinMessage<TextMsg>(doc, baseMsg, config));
                case MessageType.IMAGE:
                    return handler.ImageHandler(ConvertWeiXinMessage<ImgMsg>(doc, baseMsg, config));
                case MessageType.VOICE:
                    return handler.VoiceHandler(ConvertWeiXinMessage<VoiceMsg>(doc, baseMsg, config));
                case MessageType.VIDEO:
                    return handler.VideoHandler(ConvertWeiXinMessage<VideoMsg>(doc, baseMsg, config));
                case MessageType.LOCATION:
                    return handler.LocationHandler(ConvertWeiXinMessage<LocationMsg>(doc, baseMsg, config));
                case MessageType.LINK:
                    return handler.LinkHandler(ConvertWeiXinMessage<LinkMsg>(doc, baseMsg, config));
                case MessageType.EVENT:
                    var eventtype = (EventType)Enum.Parse(typeof(EventType), doc.Element("Event").Value.ToUpper());
                    switch (eventtype)
                    {
                        case EventType.SUBSCRIBE:
                            return handler.SubscribeHandler(ConvertWeiXinMessage<SubscribeEventMsg>(doc, baseMsg, config));
                        case EventType.UNSUBSCRIBE:
                            return handler.UnSubscribeHandler(ConvertWeiXinMessage<EventMsg>(doc, baseMsg, config));
                        case EventType.SCAN:
                            return handler.ScanHandler(ConvertWeiXinMessage<ScanQrEventMsg>(doc, baseMsg, config));
                        case EventType.LOCATION:
                            return handler.LocationEventHandler(ConvertWeiXinMessage<LocationEventMsg>(doc, baseMsg, config));
                        case EventType.CLICK:
                            return handler.MenuClickHandler(ConvertWeiXinMessage<BaseMenuEventMsg>(doc, baseMsg, config));
                        case EventType.VIEW_MINIPROGRAM:
                            return handler.MenuMiniProgramHandler(ConvertWeiXinMessage<BaseMenuEventMsg>(doc, baseMsg, config));

                        case EventType.VIEW:
                            return handler.MenuViewHandler(ConvertWeiXinMessage<ViewEventMsg>(doc, baseMsg, config));
                        case EventType.SCANCODE_PUSH:
                            return handler.MenuScanPushHandler(ConvertWeiXinMessage<ScanMenuEventMsg>(doc, baseMsg, config));
                        case EventType.SCANCODE_WAITMSG:
                            return handler.MenuScanWaitHandler(ConvertWeiXinMessage<ScanMenuEventMsg>(doc, baseMsg, config));
                        case EventType.PIC_SYSPHOTO:
                        case EventType.PIC_PHOTO_OR_ALBUM:
                        case EventType.PIC_WEIXIN:
                            return handler.MenuPicHandler(ConvertWeiXinMessage<PicMenuEventMsg>(doc, baseMsg, config));
                        case EventType.LOCATION_SELECT:
                            return handler.MenuLocationHandler(ConvertWeiXinMessage<LocationMenuEventMsg>(doc, baseMsg, config));
                        case EventType.TEMPLATESENDJOBFINISH:
                            return handler.TemplateJobEventHandler(ConvertWeiXinMessage<TemplateJobEventMsg>(doc, baseMsg, config));
                        case EventType.MASSSENDJOBFINISH:
                            return handler.GroupSendJobHandler(ConvertWeiXinMessage<GroupSendJobEventMsg>(doc, baseMsg, config));
                        case EventType.KF_CREATE_SESSION:
                            break;
                        case EventType.KF_CLOSE_SESSION:
                            break;
                        case EventType.KF_SWITCH_SESSION:
                            break;
                        case EventType.MERCHANT_ORDER:
                            break;
                        case EventType.POI_CHECK_NOTIFY:
                            return handler.PoiNotifyHandler(ConvertWeiXinMessage<PoiNotifyEventMsg>(doc, baseMsg, config));
                        case EventType.CARD_PASS_CHECK:
                        case EventType.CARD_NOT_PASS_CHECK:
                            return handler.CardCheckResultHandler(ConvertWeiXinMessage<CardCheckEventMsg>(doc, baseMsg, config));
                        case EventType.USER_GET_CARD:
                            return handler.UserGetCardHandler(ConvertWeiXinMessage<UserGetCardEventMsg>(doc, baseMsg, config));
                        case EventType.USER_GIFTING_CARD:
                            return handler.CardGiftingEventHandler(
                                ConvertWeiXinMessage<CardGiftingEventMsg>(doc, baseMsg, config));
                        case EventType.USER_DEL_CARD:
                            return handler.CardDeleteEventHandler(
                                ConvertWeiXinMessage<CardDeleteEventMsg>(doc, baseMsg, config));
                        case EventType.USER_VIEW_CARD:
                            return handler.CardViewEventHandler(
                                ConvertWeiXinMessage<CardViewEventMsg>(doc, baseMsg, config));
                        case EventType.USER_CONSUME_CARD:
                            return handler.CardConsumeEventHandler(
                                ConvertWeiXinMessage<CardConsumeEventMsg>(doc, baseMsg, config));
                        case EventType.USER_ENTER_SESSION_FROM_CARD:
                            return handler.EnterMpFromCardEventHandler(
                                ConvertWeiXinMessage<EnterMpFromCardEventMsg>(doc, baseMsg, config));
                        case EventType.UPDATE_MEMBER_CARD:
                            return handler.UpdateMemberCardEventHandler(
                                ConvertWeiXinMessage<UpdateMemberCardEventMsg>(doc, baseMsg, config));
                        case EventType.CARD_SKU_REMIND:
                            return handler.CardSkuRemindEventHandler(
                                ConvertWeiXinMessage<CardSkuRemindEventMsg>(doc, baseMsg, config));
                        case EventType.CARD_PAY_ORDER:
                            return handler.CardPayOrderEventHandler(
                                ConvertWeiXinMessage<CardPayOrderEventMsg>(doc, baseMsg, config));
                        case EventType.VERIFY_EXPIRED:
                        case EventType.QUALIFICATION_VERIFY_SUCCESS:
                        case EventType.QUALIFICATION_VERIFY_FAIL:
                        case EventType.NAMING_VERIFY_FAIL:
                        case EventType.NAMING_VERIFY_SUCCESS:
                        case EventType.ANNUAL_RENEW:
                            return handler.VerifyHandler(ConvertWeiXinMessage<VerifyEventMsg>(doc, baseMsg, config));
                        case EventType.USER_PAY_FROM_PAY_CELL:
                            return handler.UserPayHandler(ConvertWeiXinMessage<UserPayEventMsg>(doc, baseMsg, config));
                        case EventType.SUBMIT_MEMBERCARD_USER_INFO:
                            return handler.SubmitMemberUserInfoHandler(ConvertWeiXinMessage<SubmitMemberUserInfoEventMsg>(doc, baseMsg, config));
                        default:
                            break;
                    }
                    break;
                case MessageType.SHORTVIDEO:
                    handler.VideoHandler(ConvertWeiXinMessage<VideoMsg>(doc, baseMsg, config));
                    break;
                default:
                    break;
            }
            return "success";
        }

#if !NET40
        private static async Task<T> ConvertWeiXinMessageAsync<T>(XElement xml, BaseMsg baseMsg, EnterParamConfig config) where T : BaseMsg, new()
        {
            var msg = new T();
            #region 获取消息基本信息
            msg.MsgType = baseMsg.MsgType;
            msg.FromUserName = baseMsg.FromUserName;
            msg.CreateTime = baseMsg.CreateTime;
            msg.ToUserName = baseMsg.ToUserName;
            msg.MsgId = baseMsg.MsgId;
            #endregion
            if (config.IsRecordLastTime)
            {
                var key = $"lasttime_{msg.FromUserName}";
                if (OpenApi.redis != null)
                {
                    msg.LastTime = await OpenApi.redis.GetAsync<DateTime>(key);
                    //设置本次时间
                    OpenApi.redis.SetAsync(key, DateTime.Now);
                }
                else
                {
                    msg.LastTime = CacheService.Get<DateTime>(key);
                    CacheService.Add(key, DateTime.Now);
                }
            }
            await XmlUtil.ToObjectAsync<T>(msg, xml, "BaseMsg");
            msg.Param = config;
            return msg;
        }

        public async Task<string> GetResponseAsync(XElement doc, EnterParamConfig config)
        {
            var baseMsg = new BaseMsg();
            if (IsRepetition(doc, baseMsg))
            {
                //消息排重
                return "";
            }
            baseMsg.Param = config;
            var result = await handler.BeforeHandlerAsync(baseMsg, doc.ToString());
            if (!string.IsNullOrEmpty(result))
            {
                return result;
            }
            else
            {
                result = handler.BeforeHandler(baseMsg, doc.ToString());
                if (!string.IsNullOrEmpty(result))
                {
                    return result;
                }
            }
            var msgtype = (MessageType)Enum.Parse(typeof(MessageType), doc.Element("MsgType").Value.ToUpper());
            var responseTxt = "";
            switch (msgtype)
            {
                case MessageType.TEXT:
                    var txt = await ConvertWeiXinMessageAsync<TextMsg>(doc, baseMsg, config);
                    responseTxt = await handler.TextHandlerAsync(txt);
                    if (IsNullOrEmpty(responseTxt))
                    {
                        responseTxt = handler.TextHandler(txt);
                    }
                    break;
                case MessageType.IMAGE:
                    var image = await ConvertWeiXinMessageAsync<ImgMsg>(doc, baseMsg, config);
                    responseTxt = await handler.ImageHandlerAsync(image);
                    if (IsNullOrEmpty(responseTxt))
                    {
                        responseTxt = handler.ImageHandler(image);
                    }
                    break;
                case MessageType.VOICE:
                    var voice = await ConvertWeiXinMessageAsync<VoiceMsg>(doc, baseMsg, config);
                    responseTxt = await handler.VoiceHandlerAsync(voice);
                    if (IsNullOrEmpty(responseTxt))
                    {
                        responseTxt = handler.VoiceHandler(voice);
                    }
                    break;
                case MessageType.VIDEO:
                    var video = await ConvertWeiXinMessageAsync<VideoMsg>(doc, baseMsg, config);
                    responseTxt = await handler.VideoHandlerAsync(video);
                    if (IsNullOrEmpty(responseTxt))
                    {
                        responseTxt = handler.VideoHandler(video);
                    }
                    break;
                case MessageType.LOCATION:
                    var location = await ConvertWeiXinMessageAsync<LocationMsg>(doc, baseMsg, config);
                    responseTxt = await handler.LocationHandlerAsync(location);
                    if (IsNullOrEmpty(responseTxt))
                    {
                        responseTxt = handler.LocationHandler(location);
                    }
                    break;
                case MessageType.LINK:
                    var link = await ConvertWeiXinMessageAsync<LinkMsg>(doc, baseMsg, config);
                    responseTxt = await handler.LinkHandlerAsync(link);
                    if (IsNullOrEmpty(responseTxt))
                    {
                        responseTxt = handler.LinkHandler(link);
                    }
                    break;
                case MessageType.EVENT:
                    var eventtype = (EventType)Enum.Parse(typeof(EventType), doc.Element("Event").Value.ToUpper());
                    switch (eventtype)
                    {
                        case EventType.SUBSCRIBE:
                            var sub = await ConvertWeiXinMessageAsync<SubscribeEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.SubscribeHandlerAsync(sub);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.SubscribeHandler(sub);
                            }
                            break;
                        case EventType.UNSUBSCRIBE:
                            var unsub = await ConvertWeiXinMessageAsync<EventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.UnSubscribeHandlerAsync(unsub);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.UnSubscribeHandler(unsub);
                            }
                            break;
                        case EventType.SCAN:
                            var scan = await ConvertWeiXinMessageAsync<ScanQrEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.ScanHandlerAsync(scan);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.ScanHandler(scan);
                            }
                            break;
                        case EventType.LOCATION:
                            var loc = await ConvertWeiXinMessageAsync<LocationEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.LocationEventHandlerAsync(loc);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.LocationEventHandler(loc);
                            }
                            break;
                        case EventType.CLICK:
                            var click = await ConvertWeiXinMessageAsync<BaseMenuEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.MenuClickHandlerAsync(click);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.MenuClickHandler(click);
                            }
                            break;
                        case EventType.VIEW_MINIPROGRAM:
                            var mini = await ConvertWeiXinMessageAsync<BaseMenuEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.MenuMiniProgramHandlerAsync(mini);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.MenuMiniProgramHandler(mini);
                            }
                            break;
                        case EventType.VIEW:
                            var view = await ConvertWeiXinMessageAsync<ViewEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.MenuViewHandlerAsync(view);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.MenuViewHandler(view);
                            }
                            break;
                        case EventType.SCANCODE_PUSH:
                            var sp = await ConvertWeiXinMessageAsync<ScanMenuEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.MenuScanPushHandlerAsync(sp);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.MenuScanPushHandler(sp);
                            }
                            break;
                        case EventType.SCANCODE_WAITMSG:
                            var sw = await ConvertWeiXinMessageAsync<ScanMenuEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.MenuScanWaitHandlerAsync(sw);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.MenuScanWaitHandler(sw);
                            }
                            break;
                        case EventType.PIC_SYSPHOTO:
                        case EventType.PIC_PHOTO_OR_ALBUM:
                        case EventType.PIC_WEIXIN:
                            var pic = await ConvertWeiXinMessageAsync<PicMenuEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.MenuPicHandlerAsync(pic);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.MenuPicHandler(pic);
                            }
                            break;
                        case EventType.LOCATION_SELECT:
                            var ls = await ConvertWeiXinMessageAsync<LocationMenuEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.MenuLocationHandlerAsync(ls);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.MenuLocationHandler(ls);
                            }
                            break;
                        case EventType.TEMPLATESENDJOBFINISH:
                            var tjf = await ConvertWeiXinMessageAsync<TemplateJobEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.TemplateJobEventHandlerAsync(tjf);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.TemplateJobEventHandler(tjf);
                            }
                            break;
                        case EventType.MASSSENDJOBFINISH:
                            var mjf = await ConvertWeiXinMessageAsync<GroupSendJobEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.GroupSendJobHandlerAsync(mjf);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.GroupSendJobHandler(mjf);
                            }
                            break;
                        case EventType.KF_CREATE_SESSION:
                            break;
                        case EventType.KF_CLOSE_SESSION:
                            break;
                        case EventType.KF_SWITCH_SESSION:
                            break;
                        case EventType.MERCHANT_ORDER:
                            break;
                        case EventType.POI_CHECK_NOTIFY:
                            var pcn = await ConvertWeiXinMessageAsync<PoiNotifyEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.PoiNotifyHandlerAsync(pcn);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.PoiNotifyHandler(pcn);
                            }
                            break;
                        case EventType.CARD_PASS_CHECK:
                        case EventType.CARD_NOT_PASS_CHECK:
                            var cnpc = await ConvertWeiXinMessageAsync<CardCheckEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.CardCheckResultHandlerAsync(cnpc);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.CardCheckResultHandler(cnpc);
                            }
                            break;
                        case EventType.USER_GET_CARD:
                            var ugc = await ConvertWeiXinMessageAsync<UserGetCardEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.UserGetCardHandlerAsync(ugc);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.UserGetCardHandler(ugc);
                            }
                            break;
                        case EventType.USER_GIFTING_CARD:
                            var ugcc = await ConvertWeiXinMessageAsync<CardGiftingEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.CardGiftingEventHandlerAsync(ugcc);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.CardGiftingEventHandler(ugcc);
                            }
                            break;
                        case EventType.USER_DEL_CARD:
                            var udc = await ConvertWeiXinMessageAsync<CardDeleteEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.CardDeleteEventHandlerAsync(udc);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.CardDeleteEventHandler(udc);
                            }
                            break;
                        case EventType.USER_VIEW_CARD:
                            var uvc = await ConvertWeiXinMessageAsync<CardViewEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.CardViewEventHandlerAsync(uvc);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.CardViewEventHandler(uvc);
                            }
                            break;
                        case EventType.USER_CONSUME_CARD:
                            var ucc = await ConvertWeiXinMessageAsync<CardConsumeEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.CardConsumeEventHandlerAsync(ucc);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.CardConsumeEventHandler(ucc);
                            }
                            break;
                        case EventType.USER_ENTER_SESSION_FROM_CARD:
                            var uesfc = await ConvertWeiXinMessageAsync<EnterMpFromCardEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.EnterMpFromCardEventHandlerAsync(uesfc);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.EnterMpFromCardEventHandler(uesfc);
                            }
                            break;
                        case EventType.UPDATE_MEMBER_CARD:
                            var umc = await ConvertWeiXinMessageAsync<UpdateMemberCardEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.UpdateMemberCardEventHandlerAsync(umc);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.UpdateMemberCardEventHandler(umc);
                            }
                            break;
                        case EventType.CARD_SKU_REMIND:
                            var csr = await ConvertWeiXinMessageAsync<CardSkuRemindEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.CardSkuRemindEventHandlerAsync(csr);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.CardSkuRemindEventHandler(csr);
                            }
                            break;
                        case EventType.CARD_PAY_ORDER:
                            var cpo = await ConvertWeiXinMessageAsync<CardPayOrderEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.CardPayOrderEventHandlerAsync(cpo);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.CardPayOrderEventHandler(cpo);
                            }
                            break;
                        case EventType.VERIFY_EXPIRED:
                        case EventType.QUALIFICATION_VERIFY_SUCCESS:
                        case EventType.QUALIFICATION_VERIFY_FAIL:
                        case EventType.NAMING_VERIFY_FAIL:
                        case EventType.NAMING_VERIFY_SUCCESS:
                        case EventType.ANNUAL_RENEW:
                            var annual = await ConvertWeiXinMessageAsync<VerifyEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.VerifyHandlerAsync(annual);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.VerifyHandler(annual);
                            }
                            break;
                        case EventType.USER_PAY_FROM_PAY_CELL:
                            var upfc = await ConvertWeiXinMessageAsync<UserPayEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.UserPayHandlerAsync(upfc);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.UserPayHandler(upfc);
                            }
                            break;
                        case EventType.SUBMIT_MEMBERCARD_USER_INFO:
                            var smui = await ConvertWeiXinMessageAsync<SubmitMemberUserInfoEventMsg>(doc, baseMsg, config);
                            responseTxt = await handler.SubmitMemberUserInfoHandlerAsync(smui);
                            if (IsNullOrEmpty(responseTxt))
                            {
                                responseTxt = handler.SubmitMemberUserInfoHandler(smui);
                            }
                            break;
                        default:
                            break;
                    }
                    break;
                case MessageType.SHORTVIDEO:
                    var svideo = await ConvertWeiXinMessageAsync<VideoMsg>(doc, baseMsg, config);
                    responseTxt = await handler.VideoHandlerAsync(svideo);
                    if (IsNullOrEmpty(responseTxt))
                    {
                        responseTxt = handler.VideoHandler(svideo);
                    }
                    break;
                default:
                    break;
            }

            return responseTxt;
        }


#endif
    }
}
